package filejoiner;

import filejoiner.data.DataSheet;
import filejoiner.data.WorkPath;
import filejoiner.io.Serializer;
import filejoiner.util.DefaultDataSheetListener;
import java.io.File;
import java.io.IOException;
import org.apache.commons.cli.*;

/**
 *
 * @author Luis
 */
public class FileJoiner {

    private static BasicParser basicParser;
    private static Options options = new Options();
    private static Joiner joiner;
    private static File file;
    private static File mask;
    private static DataSheet dataSheet;
    private static CommandLine parse;
    private static WorkPath workPath = new WorkPath();

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException, Exception {
        options.addOption("p", true, "Directorio de trabajo");
        options.addOption("t", true, "Directorio de temporales");
        options.addOption("f", true, "Archivo a subir");
        options.addOption("m", true, "Mascara");
        options.addOption("d", true, "Datasheet");
        options.addOption("s", true, "Tamaño de los archivos");
        options.addOption("C", false, "Limpiar temporales");
        OptionGroup optionGroup = new OptionGroup();
        optionGroup.addOption(new Option("U", false, "Subir archivo"));
        optionGroup.addOption(new Option("D", false, "Descargar archivo desde datasheet"));
        optionGroup.addOption(new Option("M", false, "Partir archivo"));
        optionGroup.addOption(new Option("R", false, "Recrea el archivo desde datasheet"));
        options.addOptionGroup(optionGroup);
        basicParser = new BasicParser();
        parse = basicParser.parse(options, args);
        if (parse.hasOption("p")) {
            File path = new File(parse.getOptionValue("p"));
            if (path.isDirectory()) {
                workPath.setPath(path.getAbsolutePath() + "/");
            }
        } else {
            throw new org.apache.commons.cli.ParseException("Se tiene que especificar el directorio de trabajo: -p");
        }
        if (parse.hasOption("t")) {
            File tempPath = new File(parse.getOptionValue("t"));
            if (tempPath.isDirectory()) {
                workPath.setTempPath(tempPath.getAbsolutePath() + "/");
            }
        } else {
            File tmp = new File(workPath.getPath() + "/tmp");
            tmp.mkdir();
            workPath.setTempPath(tmp.getAbsolutePath() + "/");
        }
        joiner = new Joiner(new DefaultDataSheetListener(), workPath);
        if (parse.hasOption("U")) {
            if (parse.hasOption("d")) {
                existFile("d", true);
                dataSheet = hasDataSheet();
                dataSheet = joiner.upload(dataSheet);
            } else {
                file = existFile("f", true);
                if (parse.hasOption("s")) {
                    validateFileSize(file);
                }
                if (parse.hasOption("m")) {
                    mask = existFile("m", true);
                    validateMask(mask);
                } else {
                    throw new org.apache.commons.cli.ParseException("Se tiene que especificar una mascara: -m");
                }
                dataSheet = joiner.upload(file, mask, Integer.valueOf(parse.getOptionValue("s", "4242880")));
            }
        }
        if (parse.hasOption("D")) {
            dataSheet = hasDataSheet();
            joiner.download(dataSheet);
        }
        if (parse.hasOption("R")) {
            if (dataSheet == null) {
                dataSheet = hasDataSheet();
            }
            joiner.make(dataSheet);
        }
        if (parse.hasOption("M")) {
            if (parse.hasOption("f")) {
                file = existFile("f", true);
            } else {
                throw new org.apache.commons.cli.ParseException("Se tiene que especificar una archivo: -f");
            }
            if (parse.hasOption("s")) {
                validateFileSize(file);
            }
            if (parse.hasOption("m")) {
                mask = existFile("m", true);
                validateMask(mask);
            } else {
                throw new org.apache.commons.cli.ParseException("Se tiene que especificar una mascara: -m");
            }
            joiner.split(file, mask, Integer.valueOf(parse.getOptionValue("s", "4242880")));
        }
        if (parse.hasOption("C")) {
            if (dataSheet == null) {
                dataSheet = hasDataSheet();
            }
            joiner.clean(dataSheet);
        }
    }

    public static void validateFileSize(File file) throws ParseException {
        if (Integer.valueOf(parse.getOptionValue("s", "4242880")) > ((int) file.length())) {
            throw new org.apache.commons.cli.ParseException("El tamaño de salida de los archivos es mayor al del archivo a subir: -s");
        }
    }

    public static void validateMask(File mask) throws ParseException {
        if (((int) mask.length()) > Integer.valueOf(parse.getOptionValue("s", "4242880"))) {
            throw new org.apache.commons.cli.ParseException("El tamaño de la mascara es mayor al tamaño de salida de los archivos: -s");
        }
    }

    public static DataSheet hasDataSheet() throws ParseException {
        if (parse.hasOption("d")) {
            existFile("d", true);
            Serializer serializer = new Serializer(workPath.getPath(), parse.getOptionValue("d"));
            return (DataSheet) serializer.read();
        } else {
            throw new org.apache.commons.cli.ParseException("Se tiene que especificar un datasheet: -d");
        }
    }

    public static File existFile(String option, Boolean required) throws ParseException {
        File tmp = null;
        if (parse.hasOption(option)) {
            tmp = new File(workPath.getPath() + parse.getOptionValue(option));
            if (!tmp.isFile() || !tmp.exists()) {
                throw new org.apache.commons.cli.ParseException("El archivo " + parse.getOptionValue(option) + " no existe o no es un archivo");
            }
        } else {
            if (required) {
                throw new org.apache.commons.cli.ParseException("Se tiene que especificar una archivo: " + option);
            }
        }
        return tmp;
    }
}
